﻿using Newtonsoft.Json;
using RJCP.IO.Ports;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Management;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using UDITool;

namespace UDIServer
{
    public partial class FrmMain : Form
    {
        SerialPortStream _serialPort = null;
        string _localPath = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "udi.config");
        string _defaultCom;
        string _tempCode = null;
        int _timeOut = 0;
        string[] _allCom = GetAvailablePorts();

        Msg msg;
        private ManagementEventWatcher watcher;
        UDICode udi;

        public FrmMain()
        {
            // 监听设备插入和移除的事件
            var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 or EventType = 3");
            watcher = new ManagementEventWatcher(query);
            watcher.EventArrived += SerialPortStatusChanged;
            watcher.Start();

            msg = new Msg(this);
            InitializeComponent();
            this.StartPosition = FormStartPosition.CenterScreen;
            //this.TopMost = true;


            Task.Run(() =>
            {
                Thread.Sleep(1000);
                // 获取默认串口
                if (File.Exists(_localPath))
                {
                    _defaultCom = File.ReadAllText(_localPath);
                    AutoConn();
                }
            });


            Task.Run(() =>
            {
                while (true)
                {
                    Thread.Sleep(1000);
                    _timeOut++;
                    if (_timeOut >= 1000 * 10)
                    {
                        _timeOut = 1000 * 10;
                        _tempCode = null;
                    }
                }
            });

            Task.Run(() =>
            {
                while (true)
                {
                    Thread.Sleep(500);

                    if (_serialPort != null)
                    {
                        btnConn.Invoke(new Action(() =>
                        {
                            if (_serialPort.IsOpen)
                            {
                                btnConn.BackColor = Color.Red;
                                btnConn.Text = "断开";
                                cbbCOM.Enabled = false;
                            }
                            else
                            {
                                btnConn.BackColor = Color.Green;
                                btnConn.Text = "连接";
                                cbbCOM.Enabled = true;
                            }
                        }));
                    }

                    cbbCOM.BeginInvoke(new Action(() =>
                    {
                        if (_allCom != null && !_allCom.Contains(cbbCOM.Text)) cbbCOM.SelectedIndex = -1;
                    }));
                }
            });
        }



        #region 串口相关

        /// <summary>
        /// 自动连接
        /// </summary>
        private void AutoConn()
        {
            cbbCOM_Click(null, null);
            if (_allCom.Contains(_defaultCom))
                cbbCOM.BeginInvoke(new Action(() =>
                {
                    cbbCOM.Text = _defaultCom;
                    btnConn_Click(null, null);
                }));
        }

        /// <summary>
        /// 监听串口改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPortStatusChanged(object sender, EventArrivedEventArgs e)
        {
            lock (_allCom)
            {
                _allCom = GetAvailablePorts();

                if (_allCom.Contains(_defaultCom) && (_serialPort == null || !_serialPort.IsOpen))
                {
                    AutoConn();
                }
            }

        }

        /// <summary>
        /// 获取所有串口
        /// </summary>
        /// <returns></returns>
        private static string[] GetAvailablePorts()
        {
            var portNames = new string[0];

            try
            {
                var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity WHERE Caption LIKE '%(COM%)'");
                var results = searcher.Get();

                portNames = new string[results.Count];
                int i = 0;

                foreach (var obj in results)
                {
                    var caption = obj["Caption"].ToString();
                    var portNameStartIndex = caption.LastIndexOf("(COM") + 1;
                    var portNameEndIndex = caption.LastIndexOf(")");

                    if (portNameStartIndex >= 0 && portNameEndIndex >= 0 && portNameEndIndex > portNameStartIndex)
                    {
                        var portName = caption.Substring(portNameStartIndex, portNameEndIndex - portNameStartIndex);
                        portNames[i] = portName;
                        i++;
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理异常
            }
            return portNames;
        }


        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="com"></param>
        private void OpenCom(string com)
        {
            //配置串口参数
            _serialPort = new SerialPortStream(com, 115200, 8, Parity.None, StopBits.One);
            _serialPort.Handshake = Handshake.None;
            _serialPort.RtsEnable = true;
            _serialPort.DataReceived += SerialPort_DataReceived;
            _serialPort.ErrorReceived += SerialPort_ErrorReceived;
            _serialPort.Open();
            File.WriteAllText(_localPath, com);
            //FileAttributes attributes = File.GetAttributes(_localPath);
            //File.SetAttributes(_localPath, attributes | FileAttributes.Hidden);
            _defaultCom = com;

        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        private void CloseCom()
        {
            _serialPort.Close();
            _serialPort.DataReceived -= SerialPort_DataReceived;
            _serialPort.ErrorReceived -= SerialPort_ErrorReceived;
        }

        /// <summary>
        /// 接收数据异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            msg.Show("串口异常：" + e.ToString());
        }
        #endregion

        #region 控件相关
        /// <summary>
        /// 连接 断开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConn_Click(object sender, EventArgs e)
        {
            cbbCOM.BeginInvoke(new Action(() =>
            {
                if (_serialPort != null && _serialPort.IsOpen)
                {
                    CloseCom();
                }
                else
                {
                    if (string.IsNullOrEmpty(cbbCOM.Text) || !cbbCOM.Text.ToLower().Contains("com"))
                    {
                        msg.Show("请选择扫码枪串口");
                        return;
                    }
                    OpenCom(cbbCOM.Text);
                }
            }));

        }

        /// <summary>
        /// 点击选择框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbbCOM_Click(object sender, EventArgs e)
        {
            cbbCOM.BeginInvoke(new Action(() =>
            {
                cbbCOM.DataSource = _allCom;
            }));
        }

        /// <summary>
        /// 收回下拉框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbbCOM_DropDownClosed(object sender, EventArgs e)
        {
            if (_allCom.Length == 0)
                cbbCOM.SelectedIndex = -1;
        }
        #endregion

        /// <summary>
        /// 消息接收（主要）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (msg.IsShow)
            {
                _tempCode = null;
                return;
            }
            udi = new UDICode();
            try
            {
                Thread.Sleep(50);
                int ibtr = _serialPort.BytesToRead;
                byte[] bget = new byte[ibtr];
                _serialPort.Read(bget, 0, ibtr);
                //读取的数据
                var result = Encoding.UTF8.GetString(bget);
                if (!string.IsNullOrEmpty(_tempCode))
                {
                    result = _tempCode + "&" + result;
                }

                udi.Code = result;

                result = result.Replace("\u001d", "&").Trim();
                var firstIndex = result.IndexOf("01");
                if (firstIndex == -1 || firstIndex > 2)
                {
                    msg.Show($"{udi.Code}\r\n非UID码，两段UDI请扫描第一段（01）");
                    _tempCode = null;
                    return;
                }

                result = result.Substring(firstIndex);


                var temp = result.Replace("&", "");

                if (!Regex.IsMatch(temp, "^[a-zA-Z0-9]+$"))
                {
                    msg.Show($"{udi.Code}\r\n非UDI码");
                    _tempCode = null;
                    return;
                }

                var codes = result.Split('&').ToList();

                // 移除空的内容
                List<string> needRemove = new List<string>();
                foreach (string code in codes)
                {
                    if (string.IsNullOrEmpty(code))
                    {
                        needRemove.Add(code);
                    }

                }
                codes = codes.Where(t => !needRemove.Contains(t)).ToList();

                foreach (string code in codes)
                {
                    UDI.AnalysisUDI(udi, code);
                }

                if (
                    string.IsNullOrEmpty(udi.ExpirationDate) &&
                    string.IsNullOrEmpty(udi.ProductionDate))
                {
                    if (string.IsNullOrEmpty(_tempCode))
                        _tempCode = result;
                    else
                    {
                        _tempCode = null;
                        msg.Show("两次扫码异常，请验证后重新扫码");
                    }

                }
                else
                {
                    txtGTN.BeginInvoke(new Action(() =>
                    {
                        txtGTN.Text = udi.Di;
                        txtBatch.Text = udi.BatchNumber;
                        txtPDate.Text = udi.ProductionDate;
                        txtEDate.Text = udi.ExpirationDate;
                        txtSN.Text = udi.SerialNumber;

                        var sendMsg = JsonConvert.SerializeObject(new List<UDICode> { udi });

                        UDI.KeyOutPut(sendMsg);

                        _tempCode = null;
                    }));
                }
            }
            catch (Exception ex)
            {
                msg.Show(ex.Message);
                _tempCode = null;
                return;
            }
        }

        public void Dispose()
        {
            // 停止监听并释放资源
            if (watcher != null)
            {
                watcher.Stop();
                watcher.Dispose();
            }
        }
    }
}
